-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: identify internal function invocations in traces #8222
Conversation
3b2b1fe
to
9fd779a
Compare
Adds `Step` variant for `LogCallOrder` enum and renames it to `TraceMemberOrder`. This is useful for printing logic which relies on execution steps as well, e.g. foundry-rs/foundry#8222
5f643a4
to
216e9da
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only briefly skimmed parts of it.
I think this makes sense, I'd appreciate a few more docs, and I'll take a closer look
if self.tracer.is_none() && yes || | ||
!self.tracer.as_ref().map_or(false, |t| t.config().record_steps) && debug |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a bit hard to follow,
I wonder if we can encapsulate these two bools into an enum TracingKid
or smth, because debug also implies tracing, right?
- Adds `record_returndata_snapshots` flag to config which enables snapshots of `interpreter.return_data_buffer` - Adds `record_opcodes_filter` parameter which allows to only record specific opcodes. ref foundry-rs/foundry#8222 (comment) - Adds `gas_used` field for `CallTraceStep` This should be enough to migrate foundry's debugger to using `TracingInspector` from here, I will open PR for this later today.
ref foundry-rs/foundry#8222 ref foundry-rs/foundry#8198 Adds structs and extends `TraceWriter` to support formatting of decoded trace steps. Currently two decoding formats are supported: - Internal calls. Similar to a decoded call trace, decoded internal function invocation which spans over multiple steps. Kept as decoded function name, inputs, outputs and index of the last step. - Arbitrary strings. This might be useful for formatting decoded opcodes (e.g. adding `├─ [sload] <slot>` to trace. It might make sense to extend it to something more configurable once we start implementing this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
pending @DaniPopes
Updated |
Yeah same problem as in the debugger caused by memory snapshots |
Maybe we can disable memory decoding by default to avoid the memory consumption issue? |
Yeah, I though about disabling memory tracking if more than one test matched filters. Though not sure how to make this intuitive Should it be two separate flags, one of which does not require the test function filter? |
Updated
|
Hey @klkvr, great work on this PR! Just wanted to follow up on your comment about source maps getting messed up by the optimization step: do you mean that they're actually broken and it'd be useful to open an issue in solc or just that optimization fundamentally obfuscates the origin of an opcode as they could be reduced to fewer operations? |
@Philogy it's hard to tell, I've definitely seen situations in which source maps would point to completely unrelated chunck of code for some of the instructions after optimizations. However, I wouldn't be surprised if this has a reasonable explanation related to how inlining works internally. Sourcemaps are documented very briefly so it's hard to tell how they should behave and what we should consider a bug, and whether we can trust them after certain number of optimizations at all |
Version: Hey guys, really appreciate your efforts. I am actually facing an issue, when using Notes:
|
Ok I got it. first parameter |
Motivation
Introduces
--decode-internal
flag forforge test
,cast run
andcast call --trace
which enables decoding of internal functions in tracesExample
Example trace of random Uniswap V3 swap:
Solution
To determine when we are jumping in/out of functions we are using source map
Jump
key. However, it is not really reliable, especially after optimizations. Almost in all cases there are mismatches between number of "in"s and "out"s, so we need additional processing to correctly display subset of functions which are correctly reported.Main implementation of this tracing is in
DebugTraceIdentifier
: https://github.com/foundry-rs/foundry/blob/216e9da8a28fcc57bcba1c6c4986aa5353472cc5/crates/evm/traces/src/debug/mod.rsThe only issue with this approach is that we are losing data about entire stack of internal functions which were joined before revert
I've used default tracer from revm-inspectors instead of traces collected by
Debugger
to allow easier integration into printing logic. Using it required a small patch to inspectors: paradigmxyz/revm-inspectors#150This approach is enough to implement flamegraphs in a similar way, and can probably be extended to smarter tracking of stack/memory/calldata to also resolve input and output parameters of internal functions
Printing logic is a bit ugly at the moment
Closes: #3999 + Closes: #4351